﻿/* 
 * Copyright 2010 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Ngilead.Core
{
    /// <summary>
    /// Persistence utility contract
    /// </summary>
    public interface IPersistenceUtil
    {
        #region Session Management

        /// <summary>
        /// Open a new session
        /// </summary>
        void OpenSession();

        /// <summary>
        /// Close the session opened with 'openSession' call
        /// </summary>
        void CloseCurrentSession();

        /// <summary>
        /// Load a fresh instance of the persistent Pojo
        /// </summary>
        /// <param name="id">the clone pojo (needed for ID)</param>
        /// <param name="persistentClass">the persistent class</param>
        /// <returns>the loaded instance</returns>
        object Load(object id, Type/*Class<?>*/ persistentClass);

        /// <summary>
        /// Flush pending modifications if needed
        /// </summary>
        void FlushIfNeeded();

        #endregion

        #region Id Mamagment

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pojo"></param>
        /// <returns>the ID of the argument Hibernate Pojo</returns>
        object GetId(object pojo);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pojo"></param>
        /// <param name="persistentClass"></param>
        /// <returns>the ID of the argument DTO with the same name than the persistent class</returns>
        object GetId(object pojo, Type persistentClass);

        #endregion

        #region Persistence metadata management

        /// <summary>
        /// Indicates if the pojo is persistent or not.
        /// Its class must be declared as persistent and the pojo must
        /// have an ID
        /// </summary>
        /// <param name="pojo"></param>
        /// <returns></returns>
        bool IsPersistentPojo(object pojo);

        /// <summary>
        /// Indicates if the class is managed by the persistance container of not
        /// </summary>
        /// <param name="clazz"></param>
        /// <returns></returns>
        bool IsPersistentClass(Type clazz);

        /// <summary>
        /// Get the persistent class without proxy
        /// </summary>
        /// <param name="clazz"></param>
        /// <returns>the underlying persistent class</returns>
        Type GetUnenhancedClass(Type clazz);

        /// <summary>
        /// Indicated if the argument class is enhanced or not
        /// </summary>
        /// <param name="clazz">the persistent class</param>
        /// <returns>true is the class is enhanced, false otherwise</returns>
        bool IsEnhanced(Type clazz);

        #endregion

        #region Proxy management

        /// <summary>
        /// Indicates if the argument collection is persistent or not
        /// </summary>
        /// <param name="collectionClass">the collection class</param>
        /// <returns></returns>
        bool IsPersistentCollection(Type collectionClass);


        /// <summary>
        /// Indicates if the proxy information denote a persistent collection or not
        /// </summary>
        /// <param name="proxyInformation">the collection class</param>
        /// <returns></returns>
        bool IsDenotingPersistentCollection(Dictionary<string, object> proxyInformation);

        /// <summary>
        /// Returns the basic collection type associated with the argument persistent collection
        /// </summary>
        /// <param name="collectionClass"></param>
        /// <returns></returns>
        Type GetUnderlyingCollectionType(Type collectionClass);

        /// <summary>
        /// Indicates if the argument collection is a persistent map or not
        /// </summary>
        /// <param name="collectionClass">the collection class</param>
        /// <returns></returns>
        bool IsPersistentDictionary(Type collectionClass);

        /// <summary>
        /// Indicates if the proxy informations denote a persistent dictionary or not
        /// </summary>
        /// <param name="proxyInformation"></param>
        /// <returns></returns>
        bool IsDenotingPersistentDictionary(Dictionary<string, object> proxyInformation);

        /// <summary>
        /// Indicates if the argument is initialized or not
        /// </summary>
        /// <param name="proxy">the instance to check</param>
        /// <returns></returns>
        bool IsInitialized(object proxy);

        /// <summary>
        /// Indicates if the property in the argument is initialized or not
        /// </summary>
        /// <param name="proxy"></param>
        /// <param name="propertyName">Name of the property to be tested</param>
        /// <returns></returns>
        bool IsPropertyInitialized(object proxy, string propertyName);


        /// <summary>
        /// Initialize the argument if not
        /// </summary>
        /// <param name="proxy">the instance to initialize</param>
        /// <returns></returns>
        void Initialize(object proxy);

        /// <summary>
        /// Serialize proxy informations of the argument entity into a map of properties
        /// </summary>
        /// <param name="proxy">the proxy to serialize</param>
        /// <returns>a map of properties</returns>
        Dictionary<string, object> SerializeEntityProxy(object proxy);


        /// <summary>
        /// Create an uninitialized proxy from the proxy informations
        /// </summary>
        /// <param name="proxyInformations">the serialized proxy informations</param>
        /// <returns>the generated proxy</returns>
        object CreateEntityProxy(Dictionary<String, object> proxyInformations);

        /// <summary>
        /// Serialize a persistent collection
        /// </summary>
        /// <param name="persistentCollection">the persistent collection</param>
        /// <returns>a Map with mininmum informations needed to re-create the persistent info</returns>
        Dictionary<string, object> SerializePersistentCollection(object persistentCollection);

        /// <summary>
        /// Serialize a persistent dictionary/map
        /// </summary>
        /// <param name="persistentDictionnary">the persistent dictionary/map</param>
        /// <returns>a Map with mininmum informations needed to re-create the persistent info</returns>
        Dictionary<string, object> SerializePersistentDictionary(object persistentDictionnary);

        /// <summary>
        /// Create a persistent collection from serialized informations
        /// </summary>
        /// <param name="parent">the parent bean of the collection</param>
        /// <param name="proxyInformations">form of the persistent collection informations</param>
        /// <param name="underlyingCollection">the filled underlying collection</param>
        /// <returns>the created persistent collection</returns>
        object CreatePersistentCollection(object parent, Dictionary<String, object> proxyInformations,
                                                          object underlyingCollection);

        /// <summary>
        /// Create a persistent dictionary/map from serialized informations
        /// </summary>
        /// <param name="parent">the parent bean of the dictionary/map</param>
        /// <param name="proxyInformations">form of the persistent dictionary/map informations</param>
        /// <param name="underlyingpersistentDictionnary">the filled underlying dictionary/map</param>
        /// <returns>the created persistent dictionary/map</returns>
        object CreatePersistentDictionary(object parent, Dictionary<String, object> proxyInformations,
                                                          object underlyingpersistentDictionnary);



        #endregion
        /*----------------------------------------------------------------------------------------*/

        /*----------------------------------------------------------------------------------------*/
        #region Loading management

        /// <summary>
        /// Load an association from the parent object
        /// </summary>
        /// <param name="parentClass">class of the parent entity</param>
        /// <param name="parentId">id of the parent entity</param>
        /// <param name="propertyName">the name of the property to load</param>
        /// <returns></returns>
        object LoadAssociation(/*Class<?>*/Type parentClass, object parentId,
                                               string propertyName);

        /// <summary>
        /// Executes an EJBQL query.
        /// </summary>
        /// <param name="query">the EJBQL query</param>
        /// <param name="parameters">parameters list (can be null)</param>
        /// <returns>the query result list</returns>
        List<object> ExecuteQuery(string query, List<object> parameters);


        /// <summary>
        /// Executes an EJBQL query.
        /// </summary>
        /// <param name="query">query the EJBQL query</param>
        /// <param name="parameters">parameters list (can be null)</param>
        /// <returns>the query result list</returns>
        List<object> ExecuteQuery(string query, Dictionary<string, object> parameters);

        #endregion
        /*----------------------------------------------------------------------------------------*/
    }
}
